﻿using System;
using Game1942.Library.Background.Bodies;

namespace Game1942.Library.Background
{
    public class Position
    {
        private Point myPosition;
        private bool located;
        private readonly Element owner;
        private Body myBody;

        private Position()
        {
        }

        public Position (Element anOwner)
        {
            owner = anOwner;
            located = false;
        }

        public void SetBody(Body body)
        {
            myBody = body;
            myBody.CreateBodyOf(owner);
        }

        public Point Value
        {
            get { return myPosition; }
            set
            {
                myPosition = new Point(value);
                myBody.RelativeMove(myPosition);
            }
        }

        public bool Located
        {
            get { return located; }
        }

        public Point Dimension
        {
            get { return myBody.GetBodyDimension(); }
        }

        public bool Move(Point relative)
        {
            if (located)
                myBody.DeleteFromMap();
            
            myBody.RelativeMove(relative);
            if (!myBody.BelongsTo(Background.Instance))
            {
                myBody.RelativeMove(relative.Inverse());
                //throw new ArgumentOutOfRangeException();      Si tiras excepcion, anda para el orto
                located = false;
                return false;
            }

            myPosition.Plus(relative);

            located = Locate();     //Try to locate the Element (does not support OutofBound Positions)

            if(!located)    //If it could not be located, then crashes
            {
                var intruder = Background.Instance.GetIntruder(myBody);

                if (owner.IsEnemy(intruder))
                {
                    owner.CrashWith(intruder);
                }
                if (intruder.IsEnemy(owner))
                {
                    intruder.CrashWith(owner);
                }
            }
            
            return true;
        }

        public bool MoveTo(Point notRelativePoint)
        {
            return (Move(new Point(notRelativePoint.X - myPosition.X, notRelativePoint.Y - myPosition.Y)));
        }

        private bool Locate()
        {
            var isLocated = myBody.Locate();
            if (!isLocated)
            {
                myBody.Clean();
            }

            return isLocated;
        }

        public bool InitializeLocation (Point point)
        {
            Value = point;
            located = Locate();
            return located;
        }

        public void Deallocate()
        {
            if (located)
            {
                myBody.Clean();
            }
        }
    }
}
